#include "base64.h"


static const char *
base64char = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

/******************************************************
//功能：进行Base64编码
//传入参数：bindata:要进行Base64编码的数据
//          Len:要进行Base64编码的数据长度
//传出参数：返回编码的数据
//创建时间：2018/5/13 15:47
//修改历史记录：
********************************************************/
std::string Base64_Encode(const uint8_t *bindata, uint32_t len)
{
    uint32_t    i;
    uint8_t    current;

    uint32_t n = len/3*3;
    uint32_t remain = len-n;
    std::string base64_str;

    base64_str.reserve(n/3*4+(remain?1:0)*4+1);

    for (i=0; i<n; i+=3) {
        current     = bindata[i] >> 2;
        current    &= 0x3F;
        base64_str += base64char[current];

        current     = (bindata[i]<<4) & 0x30;
        current    |= (bindata[i+1]>>4) & 0x0F;
        base64_str += base64char[current];

        current = (bindata[i+1]<<2) & 0x3C;
        current     |= (bindata[i+2]>>6) & 0x03;
        base64_str += base64char[current];

        current = bindata[i+2] & 0x3F ;
        base64_str += base64char[current];
    }
    if (remain > 0) {
        current     =   (bindata[i] >> 2);
        current     &=  0x3F;
        base64_str += base64char[current];

        current = (bindata[i]<<4) & 0x30;
        if (remain == 1) {
            base64_str += base64char[current];
            base64_str += '=';
            base64_str += '=';
        }
        else {
            current    |= (bindata[i+1]>>4) & 0x0F;
            base64_str += base64char[current];

            current = (bindata[i+1]<<2) & 0x3C;
            base64_str += base64char[current];
            base64_str += '=';
        }
    }

    base64_str += '\0';
    return base64_str;
}

/******************************************************
//功能：进行Base64解码
//传入参数：base64:要进行Base64解码的数据
//          bindata:Base64解码后的数据
//传出参数：返回解码的数据长度
//创建时间：2018/5/13 16:30
//修改历史记录：
********************************************************/
int Base64_Decode(const char *base64, uint8_t *bindata)
{
    int         i, j;
    uint8_t     k;
    uint8_t     temp[4];

    for(i = 0,j = 0; base64[i] != '\0' ; i += 4)
    {
        memset(temp, 0xFF, sizeof(temp));

        for(k = 0; k < 64; k ++) {
            if(base64char[k] == base64[i]) {
                temp[0]= k;
                break;
            }
        }

        for(k = 0 ; k < 64 ; k ++) {
            if(base64char[k] == base64[i+1]) {
                temp[1]= k;
                break;
            }
        }

        for(k = 0 ; k < 64 ; k ++) {
            if(base64char[k] == base64[i+2]) {
                temp[2]= k;
                break;
            }
        }

        for (k = 0 ; k < 64 ; k ++) {
            if(base64char[k] == base64[i+3]) {
                temp[3]= k;
                break;
            }
        }

        bindata[j++] = ((temp[0] << 2)&0xFC) | ((temp[1]>>4)&0x03);
        if(base64[i+2] == '=')
            break;

        bindata[j++] = ((temp[1] << 4)&0xF0) | ((temp[2]>>2)&0x0F);
        if(base64[i+3] == '=')
            break;
        bindata[j++] = ((temp[2] << 6)&0xF0) | (temp[3]&0x3F);
    }

    return j;
}
